package handler

/*
 +----------------------------------------------------------------------
 + Title        : UserHandler
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2018-01-06
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : 用户处理器
 +----------------------------------------------------------------------
*/
import (
	"context"
	"encoding/json"
	"fmt"
	"golang-microgrpc-sharemod/services/user-service/models"
	pbParams "golang-microgrpc-sharemod/services/user-service/proto/params"
	pbResult "golang-microgrpc-sharemod/services/user-service/proto/result"
	pbUser "golang-microgrpc-sharemod/services/user-service/proto/user"
	"golang-microgrpc-sharemod/services/user-service/utils"
	"math"
	"strings"
	"time"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

type UserHandler struct {
	pbUser.UnimplementedUserSrvServer
}

/**
 * 新增
 *
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Email ------------------------非必传,邮箱
 * @param string Username ---------------------必传,用户名
 * @param string Password ---------------------非必传,密码
 * @param string AvatarUrl --------------------非必传,头像
 * @param uint32 Source -----------------------非必传,来源
 * @param []string Hobby ----------------------非必传,爱好
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------必传,手机号
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param uint32 Score ------------------------非必传,积分
 * @param int32 Balance -----------------------非必传,余额
 * @param map[string]string AppendInfo --------非必传,附加信息
 * @param int32 Status ------------------------非必传,状态
 * @param string Token ------------------------非必传,token
 * @param string Note -------------------------非必传,备注
 * @return *pbUser.AddUserResponse, error
 * @author huwl
 */
func (e *UserHandler) AddUser(ctx context.Context, req *pbUser.AddUserRequest) (*pbUser.AddUserResponse, error) {
	password := req.Password
	username := req.Username
	mobile := req.Mobile

	if username == "" {
		return nil, status.Errorf(codes.InvalidArgument, "用户名不能为空")
	}
	if !utils.CheckMobile(mobile) {
		return nil, status.Errorf(codes.InvalidArgument, "请输入正确格式的手机号")
	}

	//判断用户名是否重复
	var total int64
	err := models.User{}.GetTotalByParams(&models.User{}, &total, map[string]interface{}{
		"username":    username,
		"status <> ?": -2,
	})
	if err != nil || total > 0 {
		return nil, status.Errorf(codes.Aborted, "用户名已存在,请重新输入")
	}

	//判断手机号是否重复
	err = models.User{}.GetTotalByParams(&models.User{}, &total, map[string]interface{}{
		"mobile":      mobile,
		"status <> ?": -2,
	})
	if err != nil || total > 0 {
		return nil, status.Errorf(codes.Aborted, "手机号已存在,请重新输入")
	}

	bcryptPassword := ""
	if password != "" {
		bcryptPassword, _ = utils.Bcrypt(password)
	}

	var hobby []byte
	if len(req.Hobby) > 0 {
		hobby, _ = json.Marshal(req.Hobby)
	}
	var appendInfo []byte
	if len(req.AppendInfo) > 0 {
		appendInfo, _ = json.Marshal(req.AppendInfo)
	}

	user := models.User{
		Name:       req.Name,
		Nick:       req.Nick,
		Email:      req.Email,
		Username:   req.Username,
		Password:   bcryptPassword,
		AvatarUrl:  req.AvatarUrl,
		Source:     uint8(req.Source),
		Hobby:      hobby,
		Level:      uint8(req.Level),
		Mobile:     req.Mobile,
		Gender:     uint8(req.Gender),
		ProvinceId: uint16(req.ProvinceId),
		CityId:     uint16(req.CityId),
		DistrictId: uint16(req.DistrictId),
		Score:      uint32(req.Score),
		Balance:    uint32(req.Balance),
		AppendInfo: appendInfo,
		Status:     int8(req.Status),
		Token:      req.Token,
		Note:       req.Note,
	}
	i, err := models.User{}.Add(&user)
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if i <= 0 {
		return nil, status.Errorf(codes.Aborted, "新增用户失败")
	}

	return &pbUser.AddUserResponse{
		Code: 200,
		Msg:  "新增用户成功",
		User: &pbUser.User{
			Uid:        uint64(user.Uid),
			Name:       user.Name,
			Nick:       user.Nick,
			Email:      user.Email,
			Username:   user.Username,
			Password:   bcryptPassword,
			AvatarUrl:  user.AvatarUrl,
			Source:     uint32(user.Source),
			Level:      uint32(user.Level),
			Mobile:     user.Mobile,
			Gender:     uint32(user.Gender),
			ProvinceId: uint32(user.ProvinceId),
			CityId:     uint32(user.CityId),
			DistrictId: uint32(user.DistrictId),
			Score:      uint32(user.Score),
			Balance:    int32(user.Balance),
			Status:     int32(user.Status),
			Token:      user.Token,
			Note:       user.Note,
		},
	}, nil
}

/**
 * 删除
 *
 * @param string Ids --------------------------必传,用户Id支持多个
 * @return *pbResult.Result, error
 * @author huwl
 */
func (e *UserHandler) DeleteUser(ctx context.Context, req *pbParams.IdsRequest) (*pbResult.Result, error) {
	if req.Ids == "" {
		return nil, status.Errorf(codes.InvalidArgument, "用户名Id错误")
	}

	result, err := models.User{}.EditByParams(&models.User{}, map[string]interface{}{
		"status":      -2,
		"update_time": time.Now(),
	}, map[string]interface{}{"uid IN (?)": strings.Split(strings.TrimRight(req.Ids, ","), ",")})
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if result <= 0 {
		return nil, status.Errorf(codes.Aborted, "删除用户失败")
	}

	return &pbResult.Result{Code: 200, Msg: "删除用户成功"}, nil
}

/**
 * 编辑
 *
 * @param uint64 Uid --------------------------必传,用户Id
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Email ------------------------非必传,邮箱
 * @param string Username ---------------------非必传,用户名
 * @param string AvatarUrl --------------------非必传,头像
 * @param int Source --------------------------非必传,来源
 * @param []string Hobby ----------------------非必传,爱好
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------非必传,手机号
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param uint32 Score ------------------------非必传,积分
 * @param int32 Balance -----------------------非必传,余额
 * @param map[string]string AppendInfo --------非必传,附加信息
 * @param int32 Status ------------------------非必传,状态
 * @param string Token ------------------------非必传,token
 * @param string Note -------------------------非必传,备注
 * @return *pbResult.Result error
 * @author huwl
 */
func (e *UserHandler) EditUser(ctx context.Context, req *pbUser.EditUserRequest) (*pbResult.Result, error) {
	if req.Uid <= 0 {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}

	params := map[string]interface{}{"update_time": time.Now()}
	if req.Name != "" {
		params["name"] = req.Name
	}
	if req.Nick != "" {
		params["nick"] = req.Nick
	}
	if req.Email != "" {
		params["email"] = req.Email
	}
	if req.Username != "" {
		// 判断用户名是否重复
		// SELECT * FROM `mall_user` where username="轮墓边狱" and status <> -2 and uid <> 2212;
		// 查询排除当前用户,其他用户名为xxx的用户，为啥要排除自己因为编辑的时候有可能提交的是自己的用户名
		// 当提交的是自己的用户名是允许的
		var total int64
		err := models.User{}.GetTotalByParams(&models.User{}, &total, map[string]interface{}{
			"username":    req.Username,
			"status <> ?": -2,
			"uid <> ?":    req.Uid,
		})
		if err != nil || total > 0 {
			return nil, status.Errorf(codes.Aborted, "用户名已存在,请重新输入")
		}

		params["username"] = req.Username
	}
	if req.AvatarUrl != "" {
		params["avatar_url"] = req.AvatarUrl
	}
	if req.Source > 0 {
		params["source"] = req.Source
	}
	if len(req.Hobby) > 0 {
		hobby, _ := json.Marshal(req.Hobby)
		params["hobby"] = hobby
	}
	if req.Level > 0 {
		params["level"] = req.Level
	}
	if req.Mobile != "" {
		// 判断手机号是否重复
		// SELECT * FROM `mall_user` where mobile="17830247777" and status <> -2 and uid <> 2212;
		// 查询排除当前用户,其他用户名为xxx的用户，为啥要排除自己因为编辑的时候有可能提交的是自己的用户名
		// 当提交的是自己的用户名是允许的
		var total int64
		err := models.User{}.GetTotalByParams(&models.User{}, &total, map[string]interface{}{
			"mobile":      req.Mobile,
			"status <> ?": -2,
			"uid <> ?":    req.Uid,
		})
		if err != nil || total > 0 {
			return nil, status.Errorf(codes.Aborted, "手机号已存在,请重新输入")
		}
	}
	if req.Gender > 0 {
		params["gender"] = req.Gender
	}
	if req.ProvinceId > 0 {
		params["province_id"] = req.ProvinceId
	}
	if req.CityId > 0 {
		params["city_id"] = req.CityId
	}
	if req.DistrictId > 0 {
		params["district_id"] = req.DistrictId
	}
	if req.Score > 0 {
		params["score"] = req.Score
	}
	if req.Balance >= 0 {
		params["balance"] = req.Balance
	}
	if len(req.AppendInfo) > 0 {
		appendInfo, _ := json.Marshal(req.AppendInfo)
		params["append_info"] = appendInfo
	}
	if req.Token != "" {
		params["token"] = req.Token
	}
	if req.Note != "" {
		params["note"] = req.Note
	}

	i, err := models.User{}.EditByPrimaryKey(&models.User{}, params, req.Uid, "uid")
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if i <= 0 {
		return nil, status.Errorf(codes.Aborted, "编辑用户失败")
	}

	return &pbResult.Result{Code: 200, Msg: "编辑用户成功"}, nil
}

/**
 * 编辑用户状态
 *
 * @param string Ids --------------------------必传,用户ID支持多个
 * @param int64 Status ------------------------必传,状态
 * @return *pbResult.Result error
 * @author huwl
 */
func (e *UserHandler) EditUserStatus(ctx context.Context, req *pbParams.EditStatusRequest) (*pbResult.Result, error) {
	uids := strings.TrimRight(req.Ids, ",")

	if uids == "" {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}
	if req.Status == 0 {
		return nil, status.Errorf(codes.InvalidArgument, "用户状态错误")
	}

	result, err := models.User{}.EditByParams(&models.User{}, map[string]interface{}{"status": req.Status, "update_time": time.Now()}, map[string]interface{}{
		"uid IN (?)": utils.IntSplit(uids, ","),
	})
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	message := ""
	if req.Status == 1 {
		message = "启用用户"
	} else {
		message = "禁用用户"
	}
	if result <= 0 {
		return nil, status.Errorf(codes.Aborted, message+"失败")
	}

	return &pbResult.Result{Code: 200, Msg: message + "成功"}, nil
}

/**
 * 列表
 *
 * @param uint64 Uid --------------------------非必传,用户Id
 * @param string Uids -------------------------非必传,用户Id多个
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Email ------------------------非必传,邮箱
 * @param string Username ---------------------非必传,用户名
 * @param uint32 Source -----------------------非必传,来源
 * @param []string Hobby ----------------------非必传,爱好
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------非必传,手机号
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param map[string]string AppendInfo --------非必传,附加信息
 * @param string Status -----------------------非必传,状态
 * @param string StartCreateTime --------------非必传,开始创建时间
 * @param string EndCreateTime ----------------非必传,结束创建时间
 * @param string SortField --------------------非必传,排序字段
 * @param string SortType ---------------------非必传,排序方式
 * @param int32 PageSize ----------------------非必传,条数
 * @param uint32 Page -------------------------非必传,页码
 * @return *pbUser.UserListResponse, error
 * @author huwl
 */
func (e *UserHandler) UserList(ctx context.Context, req *pbUser.QueryUserRequest) (*pbUser.UserListResponse, error) {
	params := map[string]interface{}{
		"status <> ?": -2,
	}

	page := req.Page
	pageSize := req.PageSize
	sortType := req.SortType
	sortField := req.SortField

	if req.Uid > 0 {
		params["uid"] = req.Uid
	}
	if req.Uids != "" {
		params["uid IN (?)"] = utils.IntSplit(strings.TrimRight(req.Uids, ","), ",")
	}
	if req.Name != "" {
		params["name"] = req.Name
	}
	if req.Nick != "" {
		params["nick"] = req.Nick
	}
	if req.Email != "" {
		params["email"] = req.Email
	}
	if req.Username != "" {
		params["username"] = req.Username
	}
	if req.Source > 0 {
		params["source"] = req.Source
	}
	if req.Hobby != "" {
		// 查询: ["吃饭", "睡觉", "撸猫"]
		// SELECT * FROM tour_demo WHERE JSON_CONTAINS(hobby, '["吃饭"]')
		params["JSON_CONTAINS(hobby, ?)"] = fmt.Sprintf(`["%s"]`, req.Hobby)
	}
	if req.Level > 0 {
		params["level"] = req.Level
	}
	if req.Mobile != "" {
		params["mobile"] = req.Mobile
	}
	if req.Gender > 0 {
		params["gender"] = req.Gender
	}
	if req.ProvinceId > 0 {
		params["province_id"] = req.ProvinceId
	}
	if req.CityId > 0 {
		params["city_id"] = req.CityId
	}
	if req.DistrictId > 0 {
		params["district_id"] = req.DistrictId
	}
	if req.AppendInfo != "" {
		// 查询: {"job": "司机", "label": "xxxx"}
		// 使用 ->> 操作符 (MySQL 5.7.13+)
		// Where("JSON_EXTRACT(append_info, '$.job') = ?", "司机")
		params["JSON_EXTRACT(append_info, '$.job') = ?"] = req.AppendInfo
	}
	if req.Status != "all" {
		params["status IN (?)"] = utils.IntSplit(req.Status, ",")
	}
	if req.StartCreateTime != "" {
		params["create_time >= ?"] = req.StartCreateTime + " 00:00:00"
	}
	if req.EndCreateTime != "" {
		params["create_time <= ?"] = req.EndCreateTime + " 23:59:59"
	}
	if page <= 0 {
		page = 1
	}
	if pageSize == 0 {
		pageSize = 20
	}
	if sortField == "" {
		sortField = "uid"
	}
	if sortType == "" {
		sortType = "desc"
	}

	var total int64
	err := models.User{}.GetTotalByParams(&models.User{}, &total, params)
	if err != nil {
		return nil, err
	}

	users := []*pbUser.User{}
	userItems := []models.User{}
	if total > 0 {
		err := models.User{}.GetResultsByParams(&models.User{}, &userItems, params, int(page), int(pageSize), sortField+" "+sortType)
		if err != nil {
			return nil, status.Errorf(codes.Aborted, err.Error())
		}

		for _, user := range userItems {
			// 解析json数据
			var hobby []string
			json.Unmarshal(user.Hobby, &hobby)
			var appendInfo map[string]string
			json.Unmarshal(user.AppendInfo, &appendInfo)
			users = append(users, &pbUser.User{
				Uid:        uint64(user.Uid),
				Name:       user.Name,
				Nick:       user.Nick,
				Email:      user.Email,
				Username:   user.Username,
				Password:   user.Password,
				AvatarUrl:  user.AvatarUrl,
				Source:     uint32(user.Source),
				Hobby:      hobby,
				Level:      uint32(user.Level),
				Mobile:     user.Mobile,
				Gender:     uint32(user.Gender),
				ProvinceId: uint32(user.ProvinceId),
				CityId:     uint32(user.CityId),
				DistrictId: uint32(user.DistrictId),
				Score:      uint32(user.Score),
				Balance:    int32(user.Balance),
				AppendInfo: appendInfo,
				Status:     int32(user.Status),
				Token:      user.Token,
				Note:       user.Note,
				CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
				UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
			})
		}
	}

	pageTotal := math.Ceil(float64(total) / float64(pageSize))

	return &pbUser.UserListResponse{
		ListResult: &pbResult.ListCommonResult{
			Page:      int32(page),
			Total:     int32(total),
			PageSize:  pageSize,
			PageTotal: int32(pageTotal),
		},
		Users: users,
	}, nil
}

/**
 * 数量
 *
 * @param uint64 Uid --------------------------非必传,用户Id
 * @param string Uids -------------------------非必传,用户Id多个
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Email ------------------------非必传,邮箱
 * @param string Username ---------------------非必传,用户名
 * @param uint32 Source -----------------------非必传,来源
 * @param []string Hobby ----------------------非必传,爱好
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------非必传,手机号
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param map[string]string AppendInfo --------非必传,附加信息
 * @param string Status -----------------------非必传,状态
 * @param string StartCreateTime --------------非必传,开始创建时间
 * @param string EndCreateTime ----------------非必传,结束创建时间
 * @return *pbResult.TotalResult, error
 * @author huwl
 */
func (e *UserHandler) UserTotal(ctx context.Context, req *pbUser.QueryUserRequest) (*pbResult.TotalResult, error) {
	params := map[string]interface{}{
		"status <> ?": -2,
	}

	if req.Uid > 0 {
		params["uid"] = req.Uid
	}
	if req.Uids != "" {
		params["uid IN (?)"] = utils.IntSplit(strings.TrimRight(req.Uids, ","), ",")
	}
	if req.Name != "" {
		params["name"] = req.Name
	}
	if req.Nick != "" {
		params["nick"] = req.Nick
	}
	if req.Email != "" {
		params["email"] = req.Email
	}
	if req.Username != "" {
		params["username"] = req.Username
	}
	if req.Source > 0 {
		params["source"] = req.Source
	}
	if req.Hobby != "" {
		// 查询: ["吃饭", "睡觉", "撸猫"]
		// SELECT * FROM tour_demo WHERE JSON_CONTAINS(hobby, '["吃饭"]')
		params["JSON_CONTAINS(hobby, ?)"] = fmt.Sprintf(`["%s"]`, req.Hobby)
	}
	if req.Level > 0 {
		params["level"] = req.Level
	}
	if req.Mobile != "" {
		params["mobile"] = req.Mobile
	}
	if req.Gender > 0 {
		params["gender"] = req.Gender
	}
	if req.ProvinceId > 0 {
		params["province_id"] = req.ProvinceId
	}
	if req.CityId > 0 {
		params["city_id"] = req.CityId
	}
	if req.DistrictId > 0 {
		params["district_id"] = req.DistrictId
	}
	if req.AppendInfo != "" {
		// 查询: {"job": "司机", "label": "xxxx"}
		// 使用 ->> 操作符 (MySQL 5.7.13+)
		// Where("JSON_EXTRACT(append_info, '$.job') = ?", "司机")
		params["JSON_EXTRACT(append_info, '$.job') = ?"] = req.AppendInfo
	}
	if req.Status != "all" {
		params["status IN (?)"] = utils.IntSplit(req.Status, ",")
	}
	if req.StartCreateTime != "" {
		params["create_time >= ?"] = req.StartCreateTime + " 00:00:00"
	}
	if req.EndCreateTime != "" {
		params["create_time <= ?"] = req.EndCreateTime + " 23:59:59"
	}

	var total int64
	err := models.User{}.GetTotalByParams(&models.User{}, &total, params)
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	return &pbResult.TotalResult{Total: int32(total)}, nil
}

/**
 * 获取单条用户信息
 *
 * @param string Name -------------------------非必传,姓名
 * @param string Nick -------------------------非必传,昵称
 * @param string Username ---------------------非必传,用户名
 * @param uint32 Source -----------------------非必传,来源
 * @param uint32 Level ------------------------非必传,级别
 * @param string Mobile -----------------------非必传,手机号
 * @param uint32 Gender -----------------------非必传,性别
 * @param uint32 ProvinceId -------------------非必传,省Id
 * @param uint32 CityId -----------------------非必传,城市Id
 * @param uint32 DistrictId -------------------非必传,区Id
 * @param string Status -----------------------非必传,状态支持多个：1,-1
 * @return User error
 * @author huwl
 */
func (e *UserHandler) Row(ctx context.Context, req *pbUser.QueryUserRequest) (*pbUser.UserResponse, error) {
	params := map[string]interface{}{
		"status <> ?": -2,
	}

	if req.Name != "" {
		params["name"] = req.Name
	}
	if req.Nick != "" {
		params["nick"] = req.Nick
	}
	if req.Email != "" {
		params["email"] = req.Email
	}
	if req.Username != "" {
		params["username"] = req.Username
	}
	if req.Source > 0 {
		params["source"] = req.Source
	}
	if req.Level > 0 {
		params["level"] = req.Level
	}
	if req.Mobile != "" {
		params["mobile"] = req.Mobile
	}
	if req.Gender > 0 {
		params["gender"] = req.Gender
	}
	if req.ProvinceId > 0 {
		params["province_id"] = req.ProvinceId
	}
	if req.CityId > 0 {
		params["city_id"] = req.CityId
	}
	if req.DistrictId > 0 {
		params["district_id"] = req.DistrictId
	}
	if req.Status != "all" {
		params["status IN (?)"] = utils.IntSplit(req.Status, ",")
	}

	user := models.User{}
	i, err := models.User{}.Row(&models.User{}, &user, params)
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if i <= 0 {
		return nil, status.Errorf(codes.Aborted, "用户信息错误")
	}

	// 解析json数据
	var hobby []string
	json.Unmarshal(user.Hobby, &hobby)
	var appendInfo map[string]string
	json.Unmarshal(user.AppendInfo, &appendInfo)

	return &pbUser.UserResponse{
		User: &pbUser.User{
			Uid:        uint64(user.Uid),
			Name:       user.Name,
			Nick:       user.Nick,
			Email:      user.Email,
			Username:   user.Username,
			Password:   user.Password,
			AvatarUrl:  user.AvatarUrl,
			Source:     uint32(user.Source),
			Hobby:      hobby,
			Level:      uint32(user.Level),
			Mobile:     user.Mobile,
			Gender:     uint32(user.Gender),
			ProvinceId: uint32(user.ProvinceId),
			CityId:     uint32(user.CityId),
			DistrictId: uint32(user.DistrictId),
			Score:      uint32(user.Score),
			Balance:    int32(user.Balance),
			AppendInfo: appendInfo,
			Status:     int32(user.Status),
			Token:      user.Token,
			Note:       user.Note,
			CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
			UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
		},
	}, nil
}

/**
 * 多个用户ID获取用户信息
 *
 * @param string Ids --------------------------必传,用户Id支持多个
 * @return *pbUser.UserListResponse error
 * @author huwl
 */
func (e *UserHandler) Rows(ctx context.Context, req *pbParams.IdsRequest) (*pbUser.UserListResponse, error) {
	ids := strings.TrimRight(req.Ids, ",")

	if ids == "" {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}

	uids := utils.IntSplit(ids, ",")
	userIds := []interface{}{}
	for _, uid := range uids {
		userIds = append(userIds, uid)
	}

	userItems := []models.User{}
	err := models.User{}.Rows(&userItems, userIds)
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	users := []*pbUser.User{}
	for _, user := range userItems {
		// 解析json数据
		var hobby []string
		json.Unmarshal(user.Hobby, &hobby)
		var appendInfo map[string]string
		json.Unmarshal(user.AppendInfo, &appendInfo)

		users = append(users, &pbUser.User{
			Uid:        uint64(user.Uid),
			Name:       user.Name,
			Nick:       user.Nick,
			Email:      user.Email,
			Username:   user.Username,
			Password:   user.Password,
			AvatarUrl:  user.AvatarUrl,
			Source:     uint32(user.Source),
			Hobby:      hobby,
			Level:      uint32(user.Level),
			Mobile:     user.Mobile,
			Gender:     uint32(user.Gender),
			ProvinceId: uint32(user.ProvinceId),
			CityId:     uint32(user.CityId),
			DistrictId: uint32(user.DistrictId),
			Score:      uint32(user.Score),
			Balance:    int32(user.Balance),
			AppendInfo: appendInfo,
			Status:     int32(user.Status),
			Token:      user.Token,
			Note:       user.Note,
			CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
			UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
		})
	}

	return &pbUser.UserListResponse{
		Users: users,
	}, nil
}

/**
 * 详情
 *
 * @param int64 Uid ---------------------------必传,用户Id
 * @param int32 IsHaveUserAlbum ---------------必传,是否需要相册
 * @return *pbUser.UserResponse, error
 * @author huwl
 */
func (e *UserHandler) UserDetail(ctx context.Context, req *pbUser.UserDetailRequest) (*pbUser.UserResponse, error) {
	uid := req.Uid
	isHaveUserAlbum := req.IsHaveUserAlbum
	if uid <= 0 {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}

	user := models.User{}
	i, err := models.User{}.GetResultByPrimaryKey(&user, uid, "uid")
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if i <= 0 || user.Status == -2 {
		return nil, status.Errorf(codes.Aborted, "用户信息错误")
	}

	//获取用户相册
	userAlbums := []*pbUser.UserAlbum{}
	if isHaveUserAlbum == 1 {
		userAlbumItems := []models.UserAlbum{}
		err := models.UserAlbum{}.GetResultsByParams(&models.UserAlbum{}, &userAlbumItems, map[string]interface{}{
			"uid": uid,
		}, 1, -1, "id asc")
		if err != nil {
			return nil, status.Errorf(codes.Aborted, err.Error())
		}

		for _, userAlbumItem := range userAlbumItems {
			userAlbums = append(userAlbums, &pbUser.UserAlbum{
				Id:          int64(userAlbumItem.Id),
				Uid:         int64(userAlbumItem.Uid),
				ImageUrl:    userAlbumItem.ImageUrl,
				Description: userAlbumItem.Description,
				CreateTime:  userAlbumItem.CreateTime.Format("2006-01-02 15:04:05"),
				UpdateTime:  userAlbumItem.UpdateTime.Format("2006-01-02 15:04:05"),
			})
		}
	}
	return &pbUser.UserResponse{
		User: &pbUser.User{
			Uid:        uint64(user.Uid),
			Name:       user.Name,
			Nick:       user.Nick,
			Email:      user.Email,
			Username:   user.Username,
			Password:   user.Password,
			AvatarUrl:  user.AvatarUrl,
			Source:     uint32(user.Source),
			Level:      uint32(user.Level),
			Mobile:     user.Mobile,
			Gender:     uint32(user.Gender),
			ProvinceId: uint32(user.ProvinceId),
			CityId:     uint32(user.CityId),
			DistrictId: uint32(user.DistrictId),
			Score:      uint32(user.Score),
			Balance:    int32(user.Balance),
			Status:     int32(user.Status),
			Token:      user.Token,
			Note:       user.Note,
			CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
			UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
		},
		UserAlbums: userAlbums,
	}, nil
}

/**
 * 新增用户相册
 *
 * @param int64 Uid ---------------------------必传,用户Id
 * @param []*pbUser.UserAlbumParams UserAlbumParams ------必传,相册参数
 * @return *pbResult.Result error
 * @author huwl
 */
func (e *UserHandler) AddUserAlbum(ctx context.Context, req *pbUser.AddUserAlbumRequest) (*pbResult.Result, error) {
	uid := req.Uid
	userAlbumParams := req.UserAlbumParams

	if uid <= 0 {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}
	if len(userAlbumParams) <= 0 {
		return nil, status.Errorf(codes.InvalidArgument, "图片地址不能为空")
	}

	params := []models.UserAlbum{}
	for _, userAlbumParam := range userAlbumParams {
		if userAlbumParam.ImageUrl == "" {
			return nil, status.Errorf(codes.InvalidArgument, "图片地址不能为空")
		}
		params = append(params, models.UserAlbum{
			Uid:         int(uid),
			ImageUrl:    userAlbumParam.ImageUrl,
			Description: userAlbumParam.Description,
		})
	}

	result, err := models.UserAlbum{}.Add(&params)
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if result <= 0 {
		return nil, status.Errorf(codes.Aborted, "新增用户相册失败")
	}

	return &pbResult.Result{Code: 200, Msg: "新增相册成功"}, nil
}

/**
 * 获取用户相册
 *
 * @param int64 Uid ---------------------------非必传,用户Id
 * @param string SortType ---------------------非必传,排序方式
 * @param string SortField --------------------非必传,排序字段
 * @param string PageSize ---------------------非必传,条数
 * @param string Page -------------------------非必传,页码
 * @return *pbUser.UserAlbumResponse error
 * @author huwl
 */
func (e *UserHandler) GetUserAlbum(ctx context.Context, req *pbUser.GetUserAlbumRequest) (*pbUser.UserAlbumResponse, error) {
	params := map[string]interface{}{}
	if req.Uid > 0 {
		params["uid"] = req.Uid
	}

	page := req.Page
	pageSize := req.PageSize
	sortType := req.SortType
	sortField := req.SortField

	if page <= 0 {
		page = 1
	}
	if pageSize == 0 {
		pageSize = 20
	}
	if sortType == "" {
		sortType = "id"
	}
	if sortField == "" {
		sortType = "desc"
	}

	userAlbumItems := []models.UserAlbum{}
	err := models.UserAlbum{}.GetResultsByParams(&models.UserAlbum{}, &userAlbumItems, params, int(page), int(pageSize), sortField+" "+sortType)
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}

	userAlbums := []*pbUser.UserAlbum{}
	for _, userAlbumItem := range userAlbumItems {
		userAlbums = append(userAlbums, &pbUser.UserAlbum{
			Id:          int64(userAlbumItem.Id),
			ImageUrl:    userAlbumItem.ImageUrl,
			Description: userAlbumItem.Description,
			CreateTime:  userAlbumItem.CreateTime.Format("2006-01-02 15:04:05"),
			UpdateTime:  userAlbumItem.UpdateTime.Format("2006-01-02 15:04:05"),
		})
	}

	return &pbUser.UserAlbumResponse{UserAlbums: userAlbums}, nil
}

/**
 * 修改密码
 *
 * @param string raw_password -----------------必传,原密码
 * @param string new_password -----------------必传,新密码
 * @param string repassword -------------------必传,确认密码
 * @return *pbResult.Result error
 * @author huwl
 */
func (e *UserHandler) ChangePassword(ctx context.Context, req *pbUser.ChangePasswordRequest) (*pbResult.Result, error) {
	if req.Uid <= 0 {
		return nil, status.Errorf(codes.InvalidArgument, "用户Id错误")
	}
	if req.RawPassword == "" {
		return nil, status.Errorf(codes.InvalidArgument, "原密码不能为空")
	}
	if req.NewPassword == "" {
		return nil, status.Errorf(codes.InvalidArgument, "新密码不能为空")
	}

	// 获取用户信息
	user := models.User{}
	i, err := models.User{}.GetResultByPrimaryKey(&user, req.Uid, "uid")
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if i <= 0 || user.Status == -2 {
		return nil, status.Errorf(codes.Aborted, "用户信息错误")
	}

	// 判断用户原密码
	if !utils.CompareBcrypt(user.Password, req.RawPassword) {
		return nil, status.Errorf(codes.Aborted, "原密码错误")
	}

	// 修改密码
	bcryptPassword, _ := utils.Bcrypt(req.NewPassword)
	i, err = models.User{}.EditByPrimaryKey(&models.User{}, map[string]interface{}{
		"password": bcryptPassword,
	}, req.Uid, "uid")
	if err != nil {
		return nil, status.Errorf(codes.Aborted, err.Error())
	}
	if i <= 0 {
		return nil, status.Errorf(codes.Aborted, "修改密码失败")
	}

	return &pbResult.Result{Code: 200, Msg: "修改密码成功"}, nil
}
